/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.yonsei.iwb.sdt.algorithm;

import edu.yonsei.iwb.sdt.datastructure.DataStore;
import edu.yonsei.iwb.sdt.datastructure.DecomposeCandidateSet;
import edu.yonsei.iwb.sdt.datastructure.TargetInstance;
import edu.yonsei.iwb.sdt.ontology.PropertyArc;
import edu.yonsei.iwb.sdt.ontology.UnitClassModel;
import edu.yonsei.iwb.sdt.util.SDTLog;
import edu.yonsei.iwb.ts.TSSearch;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Vector;

/**
 *
 * @author DK
 */
public class SimulatedAnnealingProcessor {
    
    private Random ran = new Random();
    private double temp = 1.0;
    private boolean first = true;
    private DCSSearcher sdcs;
    
    private Vector<TargetInstance> tiset;
    private ArrayList<Vector<PropertyArc>> histPropertyArcList;
//    private ArrayList<Vector<PropertyArc>> initHistPropertyArcList;
    
    private Vector<PropertyArc> connectedPAset;
//    private ArrayList<String> lastResourceSet;
//    private PropertyArc selectedPA;
    private int selectedIndex;
    
    public SimulatedAnnealingProcessor(Vector<PropertyArc> initHistPA, Vector<TargetInstance> tiset, Vector<PropertyArc> connectedPAset, DCSSearcher sdcs) throws IOException{
        this.sdcs = sdcs;
        
        this.tiset = tiset;
        this.histPropertyArcList = new ArrayList<Vector<PropertyArc>>();
//        this.initHistPropertyArcList = new ArrayList<Vector<PropertyArc>>();
        setInitHisPropertyArcList(initHistPA, connectedPAset);
        //        this.histPAandConnectedList = new Hashtable<Vector<PropertyArc>, Vector<PropertyArc>>();
        //                ArrayList<String> lastResourceSet = sdcs.findLastPositionedResources(node.getInstanceSet(), hisPAset);
    }
    
    private void setInitHisPropertyArcList(Vector<PropertyArc> initHistPA, Vector<PropertyArc> connectedPAset) throws IOException{
        // 노드와 연결된 프로퍼티로...
        // 가면 안되는 리스트 제거
        ArrayList<String> instances = new ArrayList<String>();
        for (int i = 0; i < this.tiset.size(); i++) {
            TargetInstance ti = this.tiset.get(i);
            String uri = ti.getURI();
            instances.add(uri);
        }
        
        Vector<PropertyArc> initConnectedPA = this.sdcs.findConnectedObjectPropertyArcSet(instances);        
        for (int i = 0; i < initConnectedPA.size(); i++) {
            PropertyArc connPA = initConnectedPA.get(i);
            Vector<PropertyArc> tempHist = new Vector<PropertyArc>();
            tempHist.add(connPA);
            this.histPropertyArcList.add(tempHist);
//            this.initHistPropertyArcList.add(tempHist);
        }
    }
                
    public Vector<PropertyArc> setHistPropertyArcList(){
        if(this.first){
            int index = this.ran.nextInt(this.histPropertyArcList.size());
            Vector<PropertyArc> result = this.histPropertyArcList.get(index);            
//            this.selectedPA = result.lastElement();
            this.selectedIndex = index;
            
            this.first = false;
            return result;
        }else{
            Vector<PropertyArc> preSelectedHist = this.histPropertyArcList.remove(this.selectedIndex);
            
            connections:
            for (int i = 0; i < connectedPAset.size(); i++) {
                PropertyArc connPA = connectedPAset.get(i);
                String property = connPA.getProperty();                

                PropertyArc lastHistoryArc = preSelectedHist.lastElement();
                if (lastHistoryArc.getProperty().equals(property)) {
                    if (connPA.getDirection() != lastHistoryArc.getDirection()) {
                        continue connections;
                    }
                }
                
                Vector<PropertyArc> tempHist = new Vector<PropertyArc>(preSelectedHist);                
                tempHist.add(connPA);
                
                // 1. 이대로 더하면 전체 후보셋을 늘리고 그중에 랜덤하게 선택, 다른대안은
                this.histPropertyArcList.add(tempHist);                                  
            }
            int index = this.ran.nextInt(this.histPropertyArcList.size());
            Vector<PropertyArc> result = this.histPropertyArcList.get(index);            
//            this.selectedPA = result.lastElement();
            this.selectedIndex = index;
            return result;
            
            // 2. 새로생긴것 + 이전으로 다시 돌아간다의 경우중 하나를 선택한다.
            // 3. 이전 단계, 다음단계 계속 둘 중 하나.            
        }                 
    }
    
    public DecomposeCandidateSet findExpandedDecomposeCandidateSet() throws IOException{                
        DecomposeCandidateSet resultDCS = new DecomposeCandidateSet();
        Vector<PropertyArc> selectedHistPA = this.setHistPropertyArcList();
        
        SDTLog.log(SDTLog.DETAIL, "# Starting Candidate Refinement Search (In SA process)...\n");
        
        System.out.println("-----------------------------------------------------------------------------------------");
        for (int i = 0; i < this.histPropertyArcList.size(); i++) {
            System.out.println(" - # "+i+" Property History");
            Vector<PropertyArc> vector = this.histPropertyArcList.get(i);
            for (int j = 0; j < vector.size(); j++) {
                PropertyArc propertyArc = vector.get(j);
                System.out.println("   - hist PA : " +j+" / "+ propertyArc.toString());            
            }            
        }        
        System.out.println("-----------------------------------------------------------------------------------------");
        
        for (int i = 0; i < selectedHistPA.size(); i++) {
            PropertyArc propertyArc = selectedHistPA.get(i);
            System.out.println("  - # selected Hist PA : " +i+" / "+ propertyArc.toString());            
        }
        
        this.sdcs.searchDecomposeCandidateSet(resultDCS, tiset, selectedHistPA);
        
        this.connectedPAset = resultDCS.getConnectedPropertySet();
        
        return resultDCS;        
    }    
}
